home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / ScrollBar.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  49.5 KB  |  1,466 lines  |  [TEXT/CWIE]

  1. // ScrollBar.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp. All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import java.lang.Math;
  8. import netscape.util.*;
  9.  
  10. // When clicking in the tray, the knob should scroll until the point is
  11. //   under the mouse - ALERT!
  12.  
  13. /** View subclass that controls the display of a Scrollable object's
  14.   * contents. A ScrollBar has scroll buttons, which when clicked or held
  15.   * incrementally scroll the Scrollable object's contents, and a scroll tray,
  16.   * the area between the ScrollBar's scroll buttons that contains the
  17.   * ScrollBar's scroll knob. The scroll knob's position represents the portion
  18.   * of the Scrollable object's contentView that is currently visible within the
  19.   * Scrollable object.<p>
  20.   * The ScrollBar class implements a "proportional" scroll knob, meaning
  21.   * that the knob's length represents the percentage of the contentView
  22.   * currently visible within the Scrollable object; the ScrollBar's tray
  23.   * represents
  24.   * the contentView's total length. In other words, the knob's length is
  25.   * to the scroll tray's length as the Scrollable object's length is to its
  26.   * contentView's length. A ScrollBar is typically instantiated by a
  27.   * ScrollGroup, but need not be. You can instantiate an object implementing
  28.   * the Scrollable interface and a crollBar, and connect them by calling the
  29.   * ScrollBar's <b>setScrollableObject()</b> method and the Scrollable's
  30.   * <b>addScrollBar()</b> method.
  31.   * @see Scrollable
  32.   * @see ScrollView
  33.   * @see ScrollGroup
  34.   * @note 1.0 draws->dirtyRect
  35.   * @note 1.0 better behavior at small sizes
  36.   * @note 1.0 archiving the owner now
  37.   * @note 1.0 support for keyboard UI
  38.   */
  39.  
  40. public class ScrollBar extends View implements Target {
  41.     Scrollable  scrollableView;
  42.     Button      increaseButton, decreaseButton;
  43.     Image       knobImage, trayTopImage, trayBottomImage, trayLeftImage,
  44.                 trayRightImage;
  45.     Timer       timer;
  46.     int         scrollValue, origScrollValue, knobLength,
  47.                 lastMouseValue, lastAltMouseValue, lineIncrement, axis;
  48.     boolean     active, enabled, shouldRedraw;
  49.     float       pageSizeAsPercent;
  50.     int         pixelScrollValue;   // Not used if we lose the hack
  51.     ScrollBarOwner  scrollBarOwner;
  52.  
  53.     /** The default line scroll increment. */
  54.     public static final int     DEFAULT_LINE_INCREMENT = 12;
  55.     /** The default page scroll increment. */
  56.     public static final float   DEFAULT_PAGE_SIZE = 1.0f;
  57.  
  58.     /** Use to initialize a vertical ScrollBar to its default width.
  59.       * @private
  60.       */
  61.     public static final int     DEFAULT_WIDTH = 0;
  62.     /** Use to initialize a horizontal ScrollBar to its default height.
  63.       * @private
  64.       */
  65.     public static final int     DEFAULT_HEIGHT = 0;
  66.     /** Command updating the ScrollBar's scroll knob position and size. */
  67.     public static final String  UPDATE = "updateScrollValue";
  68.  
  69.     /** Command to scroll down by a page.   */
  70.     public static final String  SCROLL_PAGE_BACKWARD = "scrollPageBackward";
  71.     /** Command to scroll up by a page.  */
  72.     public static final String  SCROLL_PAGE_FORWARD = "scrollPageForward";
  73.     /** Command to scroll right by a page.  */
  74.     public static final String  SCROLL_LINE_BACKWARD = "scrollLineBackward";
  75.     /** Command to scroll left by a page.  */
  76.     public static final String  SCROLL_LINE_FORWARD = "scrollLineForward";
  77.  
  78.     private static final String TIMER_SCROLL_PAGE = "timerScroll";
  79.  
  80.     static final String         SCROLLVIEW_KEY = "scrollView",
  81.                                 INCREASEBUTTON_KEY = "increaseButton",
  82.                                 DECREASEBUTTON_KEY = "decreaseButton",
  83.                                 KNOBIMAGE_KEY = "image",
  84.                                 SCROLLVALUE_KEY = "scrollValue",
  85.                                 AXIS_KEY = "axis",
  86.                                 ACTIVE_KEY = "active",
  87.                                 ENABLED_KEY = "enabled",
  88.                                 LINE_INCREMENT_KEY = "lineIncrement",
  89.                                 OWNER_KEY = "owner";
  90.  
  91.     /** Constructs a ScrollBar with origin (0, 0) and zero width and
  92.       * height.
  93.       */
  94.     public ScrollBar() {
  95.         this(0, 0, 0, 0);
  96.     }
  97.  
  98.     /** Constructs a ScrollBar with bounds <B>rect</B>.
  99.       */
  100.     public ScrollBar(Rect rect) {
  101.         this(rect.x, rect.y, rect.width, rect.height);
  102.     }
  103.  
  104.     /** Constructs a ScrollBar with bounds
  105.       * (<B>x</B>,<B> y</B>, <B>width</B>, <B>height</B>). The ScrollBar
  106.       * will have a vertical orientation.
  107.       */
  108.     public ScrollBar(int x, int y, int width, int height) {
  109.         this(x, y, width, height, Scrollable.VERTICAL);
  110.     }
  111.  
  112.     /** Constructs a ScrollBar with bounds
  113.       * (<B>x</B>,<B> y</B>, <B>width</B>, <B>height</B>), and the specified
  114.       * orientation.
  115.       */
  116.     public ScrollBar(int x, int y, int width, int height, int theAxis) {
  117.         super(x, y, width, height);
  118.  
  119.         Button  button;
  120.  
  121.         axis = theAxis;
  122.         lineIncrement = DEFAULT_LINE_INCREMENT;
  123.         pageSizeAsPercent  = DEFAULT_PAGE_SIZE;
  124.         setEnabled(true);
  125.  
  126.         /* increase button */
  127.         button = new Button(0, 0, 16, 16);
  128.         button.setType(Button.CONTINUOUS_TYPE);
  129.         button.setBordered(true);
  130.         button.setRaisedBorder(BezelBorder.raisedScrollButtonBezel());
  131.         button.setLoweredBorder(BezelBorder.loweredScrollButtonBezel());
  132.         if (axis == Scrollable.HORIZONTAL) {
  133.             button.setImage(Bitmap.bitmapNamed(
  134.                       "netscape/application/ScrollRightArrow.gif"));
  135.             button.setAltImage(Bitmap.bitmapNamed(
  136.                       "netscape/application/ScrollRightArrowActive.gif"));
  137.  
  138.         } else {
  139.             button.setImage(Bitmap.bitmapNamed(
  140.                       "netscape/application/ScrollDownArrow.gif"));
  141.             button.setAltImage(Bitmap.bitmapNamed(
  142.                       "netscape/application/ScrollDownArrowActive.gif"));
  143.         }
  144.         setIncreaseButton(button);
  145.  
  146.         /* decrease button */
  147.         button = new Button(0, 0, 16, 16);
  148.         button.setType(Button.CONTINUOUS_TYPE);
  149.         button.setBordered(true);
  150.         button.setRaisedBorder(BezelBorder.raisedScrollButtonBezel());
  151.         button.setLoweredBorder(BezelBorder.loweredScrollButtonBezel());
  152.         if (axis == Scrollable.HORIZONTAL) {
  153.             button.setImage(Bitmap.bitmapNamed(
  154.                       "netscape/application/ScrollLeftArrow.gif"));
  155.             button.setAltImage(Bitmap.bitmapNamed(
  156.                       "netscape/application/ScrollLeftArrowActive.gif"));
  157.         } else {
  158.             button.setImage(Bitmap.bitmapNamed(
  159.                       "netscape/application/ScrollUpArrow.gif"));
  160.             button.setAltImage(Bitmap.bitmapNamed(
  161.                       "netscape/application/ScrollUpArrowActive.gif"));
  162.         }
  163.         setDecreaseButton(button);
  164.  
  165.         if (axis == Scrollable.HORIZONTAL) {
  166.             setHorizResizeInstruction(View.WIDTH_CAN_CHANGE);
  167.             setVertResizeInstruction(View.TOP_MARGIN_CAN_CHANGE);
  168.         } else {
  169.             setHorizResizeInstruction(View.LEFT_MARGIN_CAN_CHANGE);
  170.             setVertResizeInstruction(View.HEIGHT_CAN_CHANGE);
  171.         }
  172.  
  173.         if (axis == Scrollable.HORIZONTAL) {
  174.             setKnobImage(Bitmap.bitmapNamed(
  175.                 "netscape/application/ScrollKnobH.gif"));
  176.         } else {
  177.             setKnobImage(Bitmap.bitmapNamed(
  178.                 "netscape/application/ScrollKnobV.gif"));
  179.         }
  180.  
  181.         trayTopImage = Bitmap.bitmapNamed(
  182.                           "netscape/application/ScrollTrayTop.gif");
  183.         trayBottomImage = Bitmap.bitmapNamed(
  184.                           "netscape/application/ScrollTrayBottom.gif");
  185.         trayLeftImage = Bitmap.bitmapNamed(
  186.                           "netscape/application/ScrollTrayLeft.gif");
  187.         trayRightImage = Bitmap.bitmapNamed(
  188.                           "netscape/application/ScrollTrayRight.gif");
  189.  
  190.         /* check size and activate if large enough */
  191.         if ((axis == Scrollable.HORIZONTAL) && bounds.height == 0 ||
  192.             !(axis == Scrollable.HORIZONTAL) && bounds.width == 0) {
  193.             _adjustToFit();
  194.         }
  195.         _computeScrollValue();
  196.         _setupKeyboard();
  197.  
  198.     }
  199.  
  200.  
  201.     /** Overridden to return <b>false</b> (ScrollBars are opaque). */
  202.     public boolean isTransparent() {
  203.         return false;
  204.     }
  205.  
  206.     /** Returns a Rect describing the ScrollBar's "interior," the ScrollBar's
  207.       * bounds minus its left, right, top and bottom borders.
  208.       */
  209.     public Rect interiorRect() {
  210.         return Rect.newRect(1, 1, width() - 2, height() - 2);
  211.     }
  212.  
  213.     /** Returns the ScrollBar's minimum size, which is the ScrollBar's border
  214.       * widths and heights plus the area required to display its scroll
  215.       * buttons.
  216.       */
  217.     public Size minSize() {
  218.         int     width, height;
  219.  
  220. //ALERT!!
  221. //        if (_minSize != null) {
  222. //            return new Size(_minSize);
  223. //        }
  224.  
  225.         if (increaseButton != null) {
  226.             width = increaseButton.bounds.width;
  227.             height = increaseButton.bounds.height;
  228.         } else {
  229.             width = height = 0;
  230.         }
  231.         if (decreaseButton != null) {
  232.             if (axis == Scrollable.HORIZONTAL) {
  233.                 width += decreaseButton.bounds.width;
  234.                 if (height < decreaseButton.bounds.height) {
  235.                     height = decreaseButton.bounds.height;
  236.                 }
  237.             } else {
  238.                 if (width < decreaseButton.bounds.width) {
  239.                     width = decreaseButton.bounds.width;
  240.                 }
  241.                 height += decreaseButton.bounds.height;
  242.             }
  243.         }
  244.  
  245.         return new Size(width + 2, height + 2);
  246.     }
  247.  
  248.     /* Makes sure a vertical ScrollBar is wide enough and a horizontal
  249.      * ScrollBar is tall enough for its buttons.
  250.      */
  251.     void _adjustToFit() {
  252.         Size    minSize;
  253.  
  254.         minSize = minSize();
  255.         if (axis == Scrollable.HORIZONTAL) {
  256.             sizeTo(bounds.width, minSize.height);
  257.         } else {
  258.             sizeTo(minSize.width, bounds.height);
  259.         }
  260.     }
  261.  
  262.     /** Overridden to ensure there is room enough for the scroll Buttons.
  263.       */
  264.     public void didSizeBy(int deltaWidth, int deltaHeight) {
  265.         super.didSizeBy(deltaWidth, deltaHeight);
  266.         _computeScrollValue();
  267.     }
  268.  
  269.  
  270. /* scroll buttons */
  271.  
  272.     /** Makes <b>aButton</b> the ScrollBar's "increase" Button, the
  273.       * the Button that scrolls to the right in a horizontal ScrollBar and
  274.       * scrolls down in a vertical ScrollBar.  Sets the Button's resize
  275.       * instructions and command it sends when clicked.
  276.       */
  277.     public void setIncreaseButton(Button aButton) {
  278.         if (increaseButton != null) {
  279.             increaseButton.removeFromSuperview();
  280.         }
  281.  
  282.         increaseButton = aButton;
  283.         if (increaseButton != null) {
  284.             increaseButton.setTarget(this);
  285.  
  286.             increaseButton.setCommand(SCROLL_LINE_FORWARD);
  287.             if (axis == Scrollable.HORIZONTAL) {
  288.                 increaseButton.setHorizResizeInstruction(
  289.                     View.LEFT_MARGIN_CAN_CHANGE);
  290.                 increaseButton.setVertResizeInstruction(
  291.                     View.HEIGHT_CAN_CHANGE);
  292.             } else {
  293.                 increaseButton.setHorizResizeInstruction(
  294.                     View.WIDTH_CAN_CHANGE);
  295.                 increaseButton.setVertResizeInstruction(
  296.                     View.TOP_MARGIN_CAN_CHANGE);
  297.             }
  298.  
  299.             /* make sure just enough room to properly display the button */
  300.             _adjustToFit();
  301.         }
  302.  
  303.         if (enabled && active) {
  304.             addParts();
  305.         }
  306.     }
  307.  
  308.     /** Returns the ScrollBar's "increase" Button.
  309.       * @see #setIncreaseButton
  310.       */
  311.     public Button increaseButton() {
  312.         return increaseButton;
  313.     }
  314.  
  315.     /** Makes <B>aButton</B> the ScrollBar's "decrease" Button, the Button
  316.       * that scrolls
  317.       * to the left in a horizontal ScrollBar and scrolls up in a vertical
  318.       * ScrollBar. Sets the Button's resize instructions and the command that
  319.       * it sends when clicked.
  320.       */
  321.     public void setDecreaseButton(Button aButton) {
  322.         if (decreaseButton != null) {
  323.             decreaseButton.removeFromSuperview();
  324.         }
  325.  
  326.         decreaseButton = aButton;
  327.         if (decreaseButton != null) {
  328.             decreaseButton.setTarget(this);
  329.  
  330.             decreaseButton.setCommand(SCROLL_LINE_BACKWARD);
  331.             if (axis == Scrollable.HORIZONTAL) {
  332.                 decreaseButton.setHorizResizeInstruction(
  333.                     View.RIGHT_MARGIN_CAN_CHANGE);
  334.                 decreaseButton.setVertResizeInstruction(
  335.                     View.HEIGHT_CAN_CHANGE);
  336.             } else {
  337.                 decreaseButton.setHorizResizeInstruction(
  338.                     View.WIDTH_CAN_CHANGE);
  339.                 decreaseButton.setVertResizeInstruction(
  340.                     View.BOTTOM_MARGIN_CAN_CHANGE);
  341.             }
  342.  
  343.             /* make sure just enough room to properly display the button */
  344.             _adjustToFit();
  345.         }
  346.         if (enabled && active) {
  347.             addParts();
  348.         }
  349.     }
  350.  
  351.     /** Returns the ScrollBar's "decrease" Button.
  352.       * @see #setDecreaseButton
  353.       */
  354.     public Button decreaseButton() {
  355.         return decreaseButton;
  356.     }
  357.  
  358.     /** Adds the ScrollBar's scroll Buttons to the ScrollBar. Called whenever
  359.       * the ScrollBar switches from the disabled to enabled or inactive to
  360.       * active states. Override to add a ScrollBar subclass' additional
  361.       * controls.
  362.       */
  363.     public void addParts() {
  364.         int     x, y;
  365.  
  366.         x = 1;
  367.         y = 1;
  368.  
  369.         if (decreaseButton != null) {
  370.             decreaseButton.moveTo(x, y);
  371.         }
  372.         if (axis == Scrollable.HORIZONTAL) {
  373.             if (increaseButton != null) {
  374.                 increaseButton.moveTo(width() - 1 - increaseButton.width(), y);
  375.             }
  376.         } else {
  377.             if (increaseButton != null) {
  378.                 increaseButton.moveTo(x, height() - 1 -
  379.                                       increaseButton.height());
  380.             }
  381.         }
  382.  
  383.         addSubview(increaseButton);
  384.         addSubview(decreaseButton);
  385.     }
  386.  
  387.     /** Removes the ScrollBar's scroll Buttons from the ScrollBar. Called
  388.       * whenever the ScrollBar switches from the enabled to disabled or active
  389.       * to inactive states. Override to remove a ScrollBar subclass' additional
  390.       * controls.
  391.       */
  392.     public void removeParts() {
  393.         if (increaseButton != null) {
  394.             increaseButton.removeFromSuperview();
  395.         }
  396.         if (decreaseButton != null) {
  397.             decreaseButton.removeFromSuperview();
  398.         }
  399.     }
  400.  
  401.  
  402.  
  403. /* scrollView */
  404.  
  405.  
  406.     /** Sets the ScrollBar's Scrollable object, the object that the ScrollBar
  407.       * sends scroll commands to. Normally you will also have to add this
  408.       * ScrollBar to the Scrollable object's list of objects it notifies of
  409.       * of scroll changes.
  410.       * @see ScrollView#addScrollBar
  411.       */
  412.     public void setScrollableObject(Scrollable aScrollableView) {
  413.         if (scrollableView == aScrollableView) {
  414.             return;
  415.         }
  416.  
  417.         scrollableView = aScrollableView;
  418.         _computeScrollValue();
  419.     }
  420.  
  421.     /** Returns the ScrollBar's Scrollable object, the object to which the
  422.       * ScrollBar sends scroll commands.
  423.       * @see #setScrollableObject
  424.       */
  425.     public Scrollable scrollableObject() {
  426.         return scrollableView;
  427.     }
  428.  
  429.     /** Sets the ScrollBar owner, the object that receives notifications
  430.       * regarding the ScrollBar's state.
  431.       * @see ScrollBarOwner
  432.       */
  433.     public void setScrollBarOwner(ScrollBarOwner owner) {
  434.         scrollBarOwner = owner;
  435.     }
  436.  
  437.     /** Returns the ScrollBar owner, the object that receives notifications
  438.       * regarding the ScrollBar's state.
  439.       * @see #setScrollBarOwner
  440.       */
  441.     public ScrollBarOwner scrollBarOwner()  {
  442.         return scrollBarOwner;
  443.     }
  444.  
  445.  
  446. /* scroll tray */
  447.  
  448.  
  449.     /** Returns a Rect describing the ScrollBar's "tray," the ScrollBar's
  450.       * interior minus the area covered by its scroll Buttons and its
  451.       * border.  Override
  452.       * this method to return the appropriate tray Rect if you create a
  453.       * ScrollBar subclass that has additional controls or does not
  454.       * have a one pixel border.
  455.       */
  456.     public Rect scrollTrayRect() {
  457.         int     x, maxX, y, maxY;
  458.  
  459.         if (axis == Scrollable.HORIZONTAL) {
  460.             /* have to compute by hand since the button may not be a subview
  461.              * and therefore may not have the correct coordinates
  462.              */
  463.             x = 1;
  464.             if (decreaseButton != null) {
  465.                 x += decreaseButton.bounds.width;
  466.             }
  467.             maxX = width() - 1;
  468.             if (increaseButton != null) {
  469.                 maxX -= increaseButton.width();
  470.             }
  471.  
  472.             return Rect.newRect(x, 1, maxX - x, height() - 2);
  473.         } else {
  474.             y = 1;
  475.             if (decreaseButton != null) {
  476.                 y += decreaseButton.height();
  477.             }
  478.             maxY = height() - 1;
  479.             if (increaseButton != null) {
  480.                 maxY -= increaseButton.height();
  481.             }
  482.  
  483.             return Rect.newRect(1, y, width() - 2, maxY - y);
  484.         }
  485.     }
  486.  
  487.     /** Returns the length of the scroll tray, the portion of the ScrollBar
  488.       * not covered by controls, containing the ScrollBar's knob.  Returns the
  489.       * distance (height if vertical or width if horizontal) from the Rect
  490.       * returned by <b>scrollTrayRect()</b>.
  491.       * @see #scrollTrayRect
  492.       */
  493.     public int scrollTrayLength() {
  494.         Rect    scrollTrayRect;
  495.         int     length;
  496.  
  497.         scrollTrayRect = scrollTrayRect();
  498.         length = (axis == Scrollable.HORIZONTAL) ? scrollTrayRect.width
  499.                                                  : scrollTrayRect.height;
  500.         Rect.returnRect(scrollTrayRect);
  501.  
  502.         return length;
  503.     }
  504.  
  505.  
  506.  
  507. /* scroll knob */
  508.  
  509.  
  510.     /** Sets the knob's image. */
  511.     public void setKnobImage(Image anImage) {
  512.         knobImage = anImage;
  513.  
  514.         /*
  515.          * make sure just enough room to properly display the image (if
  516.          * the scoller's size is based on its knob image
  517.          */
  518.         _adjustToFit();
  519.     }
  520.  
  521.     /** Returns the knob's image.
  522.       * @see #setKnobImage
  523.       */
  524.     public Image knobImage() {
  525.         return knobImage;
  526.     }
  527.  
  528.     /** Returns a Rect describing the ScrollBar's "knob," the rectangular
  529.       * control the user can click and drag to cause the ScrollBar's
  530.       * Scrollable to scroll.  Computes the rect based on the ScrollBar's
  531.       * scroll value and knob length.
  532.       * @see #scrollValue
  533.       * @see #knobLength
  534.       */
  535.     public Rect knobRect() {
  536.         Rect    tmpRect;
  537.         int     x, y, width, height;
  538.  
  539.         tmpRect = scrollTrayRect();
  540.         if (axis == Scrollable.HORIZONTAL) {
  541.             x = tmpRect.x + scrollValue;
  542.             y = tmpRect.y;
  543.             width = knobLength;
  544.             height = tmpRect.height;
  545.         } else {
  546.             x = tmpRect.x;
  547.             y = tmpRect.y + scrollValue;
  548.             width = tmpRect.width;
  549.             height = knobLength;
  550.         }
  551.  
  552.         tmpRect.setBounds(x, y, width, height);
  553.  
  554.         return tmpRect;
  555.     }
  556.     /** Sets the length of the ScrollBar's scroll knob. You never call this
  557.       * method, but if your ScrollBar subclass does not want a proportional
  558.       * scroll knob, you can override it to prevent the ScrollBar's knob length
  559.       * from changing.
  560.       */
  561.     public void setKnobLength(int newKnobLength) {
  562.         int     scrollTrayLength;
  563.  
  564.         scrollTrayLength = scrollTrayLength();
  565.         if (newKnobLength < minKnobLength()) {
  566.             newKnobLength = minKnobLength();
  567.         } else if (newKnobLength > scrollTrayLength) {
  568.             newKnobLength = scrollTrayLength;
  569.         }
  570.         knobLength = newKnobLength;
  571.     }
  572.  
  573.     /** Returns the scroll knob's current length.
  574.       * @see #setKnobLength
  575.       */
  576.     public int knobLength() {
  577.         return knobLength;
  578.     }
  579.  
  580.     /** Returns the scroll knob's minimum length. By default, this is the
  581.       * same as the scroll knob's width or, for a horizontal ScrollBar, its
  582.       * height.
  583.       */
  584.     public int minKnobLength() {
  585.         if (axis == Scrollable.HORIZONTAL) {
  586.             return height() - 2;
  587.         }
  588.  
  589.         return width() - 2;
  590.     }
  591.  
  592.  
  593.  
  594. /* actions */
  595.  
  596.  
  597.     /** Enables or disables the ScrollBar and its constituent parts. A disabled
  598.       * ScrollBar does not respond to mouse clicks and does not display its
  599.       * scroll Buttons or knob.
  600.       */
  601.     public void setEnabled(boolean value) {
  602.         if (value == enabled) {
  603.             return;
  604.         }
  605.  
  606.         enabled = value;
  607.  
  608.         if (active && enabled) {
  609.             addParts();
  610.         } else if (!enabled) {
  611.             removeParts();
  612.         } else {
  613.             return;
  614.         }
  615.  
  616.         setDirty(true);
  617.  
  618.         if(scrollBarOwner != null)  {
  619.             if(enabled)
  620.                 scrollBarOwner.scrollBarWasEnabled(this);
  621.             else
  622.                 scrollBarOwner.scrollBarWasDisabled(this);
  623.         }
  624.  
  625.     }
  626.  
  627.     /** Returns <b>true</b> if the ScrollBar is enabled.
  628.       * @see #setEnabled
  629.       */
  630.     public boolean isEnabled() {
  631.         return enabled;
  632.     }
  633.  
  634.    /** Activates or deactivates the ScrollBar and its constituent parts. An
  635.      * inactive ScrollBar does not respond to mouse clicks and does not display
  636.      * its scroll Buttons or knob. ScrollBars automatically become inactive
  637.      * whenever they do not have a Scrollable to send scroll commands to, or
  638.      * when the Scrollable's contentView is smaller than the Scrollable
  639.      * itself (there is nothing to scroll into view). If you want to disable a
  640.      * ScrollBar, call its <B>setEnabled()</B> method.
  641.      * @see #setEnabled
  642.      */
  643.     public void setActive(boolean value) {
  644.         if (value == active) {
  645.             return;
  646.         }
  647.  
  648.         active = value;
  649.  
  650.         if (active && enabled) {
  651.             addParts();
  652.         } else if (!active) {
  653.             removeParts();
  654.         }
  655.  
  656.         setDirty(true);
  657.  
  658.         if(scrollBarOwner != null)  {
  659.             if(active)
  660.                 scrollBarOwner.scrollBarDidBecomeActive(this);
  661.             else
  662.                 scrollBarOwner.scrollBarDidBecomeInactive(this);
  663.         }
  664.  
  665.     }
  666.  
  667.     /** Returns <b>true</b> if the ScrollBar is active.
  668.       * @see #setActive
  669.       */
  670.     public boolean isActive() {
  671.         return active;
  672.     }
  673.  
  674.  
  675.  
  676. /* drawing */
  677.  
  678.     /** Draws the ScrollBar's knob and Image within <B>rect</B>. You never
  679.       * call this method directly, but should override
  680.       * it to produce custom knob drawing.
  681.       */
  682.     public void drawViewKnobInRect(Graphics g, Rect rect) {
  683.         Rect    tmpRect;
  684.  
  685.         BezelBorder.raisedScrollButtonBezel().drawInRect(g, rect);
  686.         g.setColor(Color.lightGray);
  687.         g.fillRect(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);
  688.  
  689.         if (knobImage != null) {
  690.             knobImage.drawCentered(g, rect);
  691.         }
  692.     }
  693.  
  694.     /** Draws the ScrollBar.  Eventually calls <b>drawViewKnobInRect()</b>.
  695.       * You never call this method directly.  Call the ScrollBar's
  696.       * <b>draw()</b> method to draw the ScrollBar.
  697.       * @see #drawViewKnobInRect
  698.       */
  699.     public void drawView(Graphics g) {
  700.         Rect    interiorRect, areaRect, knobRect;
  701.         int     x, y, width, height, maxX, maxY, otherX, otherY,
  702.                 beforeY, beforeX, buttonSize;
  703.  
  704.         /* draw the outside border */
  705.         g.setColor(Color.gray153);
  706.         g.drawLine(0, 0, 0, height() - 1);
  707.         g.drawLine(1, 0, width() - 1, 0);
  708.  
  709.         g.setColor(Color.gray231);
  710.         g.drawLine(width() - 1, 0, width() - 1, height());
  711.         g.drawLine(0, height() - 1, width() - 1, height() - 1);
  712.  
  713.         areaRect = scrollTrayRect();
  714.  
  715.         x = interiorRect().x;
  716.         y = interiorRect().y;
  717.         maxX = interiorRect().maxX();
  718.         maxY = interiorRect().maxY();
  719.         beforeX = areaRect.x;
  720.         beforeY = areaRect.y;
  721.         otherX = areaRect.x + areaRect.width;
  722.         otherY = areaRect.y + areaRect.height;
  723.  
  724.         if (!isEnabled() || !isActive()) {
  725.             if (axis == Scrollable.HORIZONTAL) {
  726.                 g.setColor(Color.lightGray);
  727.                 g.fillRect(x + 1, y + 1, beforeX - 3, maxY - 3);
  728.                 g.fillRect(otherX + 1, y + 1, maxX - otherX - 2, maxY - 3);
  729.                 g.fillRect(areaRect.x + 1, areaRect.y + 1,
  730.                            areaRect.width - 2, areaRect.height - 2);
  731.  
  732.                 g.setColor(Color.gray153);
  733.                 g.drawLine(x, maxY - 1, maxX - 1, maxY - 1);
  734.                 g.drawLine(maxX - 1, y, maxX - 1, maxY - 2);
  735.                 g.drawLine(beforeX - 1, y, beforeX - 1, maxY - 2);
  736.                 g.drawLine(otherX - 1, y, otherX - 1, maxY - 2);
  737.  
  738.                 // draw the decrease arrow
  739.                 g.drawLine(x + 5, y + 7, x + 5, y + 8);
  740.                 g.drawLine(x + 6, y + 6, x + 6, y + 9);
  741.                 g.drawLine(x + 7, y + 5, x + 7, y + 10);
  742.                 g.drawLine(x + 8, y + 4, x + 8, y + 11);
  743.                 g.drawLine(x + 9, y + 3, x + 9, y + 12);
  744.  
  745.                 // draw the increase arrow
  746.                 g.drawLine(otherX + 6, y + 3, otherX + 6, y + 12);
  747.                 g.drawLine(otherX + 7, y + 4, otherX + 7, y + 11);
  748.                 g.drawLine(otherX + 8, y + 5, otherX + 8, y + 10);
  749.                 g.drawLine(otherX + 9, y + 6, otherX + 9, y + 9);
  750.                 g.drawLine(otherX + 10, y + 7, otherX + 10, y + 8);
  751.  
  752.                 g.setColor(Color.gray231);
  753.                 g.drawLine(x, y, x, maxY - 2);
  754.                 g.drawLine(x + 1, y, beforeX - 2, y);
  755.                 g.drawLine(beforeX, y, beforeX, maxY - 2);
  756.                 g.drawLine(beforeX + 1, y, otherX - 2, y);
  757.                 g.drawLine(otherX, y, otherX, maxY - 2);
  758.                 g.drawLine(otherX + 1, y, maxX - 2, y);
  759.             } else {
  760.                 g.setColor(Color.lightGray);
  761.                 g.fillRect(x + 1, y + 1, maxX - 3, beforeY - 3);
  762.                 g.fillRect(x + 1, otherY + 1, maxX - 3, maxY - otherY - 2);
  763.                 g.fillRect(areaRect.x + 1, areaRect.y + 1,
  764.                            areaRect.width - 2, areaRect.height - 2);
  765.  
  766.                 g.setColor(Color.gray153);
  767.                 g.drawLine(maxX - 1, y, maxX - 1, maxY - 1);
  768.                 g.drawLine(x, maxY - 1, maxX - 2, maxY - 1);
  769.                 g.drawLine(x, beforeY - 1, maxX - 2, beforeY - 1);
  770.                 g.drawLine(x, otherY - 1, maxX - 2, otherY - 1);
  771.  
  772.                 // draw the increase arrow
  773.                 g.drawLine(x + 7, y + 5, x + 8, y + 5);
  774.                 g.drawLine(x + 6, y + 6, x + 9, y + 6);
  775.                 g.drawLine(x + 5, y + 7, x + 10, y + 7);
  776.                 g.drawLine(x + 4, y + 8, x + 11, y + 8);
  777.                 g.drawLine(x + 3, y + 9, x + 12, y + 9);
  778.  
  779.                 // draw the decrease arrow
  780.                 g.drawLine(x + 3, otherY + 6, x + 12, otherY + 6);
  781.                 g.drawLine(x + 4, otherY + 7, x + 11, otherY + 7);
  782.                 g.drawLine(x + 5, otherY + 8, x + 10, otherY + 8);
  783.                 g.drawLine(x + 6, otherY + 9, x + 9, otherY + 9);
  784.                 g.drawLine(x + 7, otherY + 10, x + 8, otherY + 10);
  785.  
  786.                 g.setColor(Color.gray231);
  787.                 g.drawLine(x, y, maxX - 2, y);
  788.                 g.drawLine(x, y + 1, x, beforeY - 2);
  789.                 g.drawLine(x, beforeY, maxX - 2, beforeY);
  790.                 g.drawLine(x, beforeY + 1, x, otherY - 2);
  791.                 g.drawLine(x, otherY, maxX - 2, otherY);
  792.                 g.drawLine(x, otherY + 1, x, maxY - 2);
  793.             }
  794.             Rect.returnRect(areaRect);
  795.             return;
  796.         }
  797.  
  798.         if (knobLength <= scrollTrayLength()) {
  799.             /// There is a knob that can be scrolled in the tray, draw
  800.             /// the tray and the kob properly.
  801.             x = areaRect.x;
  802.             maxX = areaRect.maxX();
  803.             y = areaRect.y;
  804.             maxY = areaRect.maxY();
  805.  
  806.             if (axis == Scrollable.HORIZONTAL) {
  807.                 beforeX = x + scrollValue - 1;
  808.                 otherX = x + scrollValue + knobLength;
  809.  
  810.                 if (scrollValue > 0) {
  811.                     g.setColor(Color.gray153);
  812.                     g.drawLine(x, y, beforeX, y);
  813.                     g.drawLine(x, y + 1, x, maxY - 2);
  814.  
  815.                     trayTopImage.drawTiled(g, x + 1, y + 1, beforeX - x, 1);
  816.                     trayBottomImage.drawTiled(g, x + 1, maxY - 1, beforeX - x, 1);
  817.  
  818.                     trayLeftImage.drawTiled(g, x + 1, y + 1, 1, maxY - 3);
  819.  
  820.                     g.setColor(Color.lightGray);
  821.                     g.fillRect(x + 2, y + 2, beforeX - x - 1, maxY - y - 3);
  822.                 }
  823.                 if (otherX < maxX) {
  824.                     g.setColor(Color.gray153);
  825.                     g.drawLine(otherX, y, maxX - 2, y);
  826.                     g.drawLine(maxX - 1, y, maxX - 1, maxY - 1);
  827.  
  828.                     trayTopImage.drawTiled(g, otherX, y + 1, maxX - otherX - 1, 1);
  829.                     trayBottomImage.drawTiled(g, otherX, maxY - 1,
  830.                                               maxX - otherX - 1, 1);
  831.  
  832.                     trayLeftImage.drawTiled(g, otherX, y + 1, 1, maxY - 3);
  833.                     trayRightImage.drawTiled(g, maxX - 2, y + 1, 1, maxY - 3);
  834.  
  835.                     g.setColor(Color.lightGray);
  836.                     g.fillRect(otherX + 1, y + 2, maxX - otherX - 3, maxY - y - 3);
  837.                 }
  838.             } else {
  839.                 beforeY = y + scrollValue - 1;
  840.                 otherY = y + scrollValue + knobLength;
  841.  
  842.                 if (scrollValue > 0) {
  843.                     g.setColor(Color.gray153);
  844.                     g.drawLine(x, y + 1, x, beforeY);
  845.                     g.drawLine(x, y, maxX - 1, y);
  846.  
  847.                     trayTopImage.drawTiled(g, x + 1, y + 1, maxX - 2, 1);
  848.  
  849.                     trayLeftImage.drawTiled(g, x + 1, y + 1, 1, beforeY - y);
  850.                     trayRightImage.drawTiled(g, maxX - 1, y + 1, 1, beforeY - y);
  851.  
  852.                     g.setColor(Color.lightGray);
  853.                     g.fillRect(x + 2, y + 2, maxX - x - 3, beforeY - y - 1);
  854.                 }
  855.                 if (otherY < maxY) {
  856.                     g.setColor(Color.gray153);
  857.                     g.drawLine(x, otherY, x, maxY - 2);
  858.                     g.drawLine(x, maxY - 1, maxX - 1, maxY - 1);
  859.  
  860.                     trayTopImage.drawTiled(g, x + 1, otherY, maxX - x - 2, 1);
  861.                     trayBottomImage.drawTiled(g, x + 1, maxY - 2, maxX - x - 1, 1);
  862.  
  863.                     trayLeftImage.drawTiled(g, x + 1, otherY, 1,
  864.                                             maxY - otherY - 2);
  865.                     trayRightImage.drawTiled(g, maxX - 1, otherY, 1,
  866.                                              maxY - otherY - 2);
  867.  
  868.                     g.setColor(Color.lightGray);
  869.                     g.fillRect(x + 2, otherY + 1, maxX - x - 3, maxY - otherY - 3);
  870.                 }
  871.             }
  872.             Rect.returnRect(areaRect);
  873.  
  874.             /* draw the knob */
  875.             knobRect = knobRect();
  876.             drawViewKnobInRect(g, knobRect);
  877.             Rect.returnRect(knobRect);
  878.         } else  {
  879.             // There is not enough room to display the knob, draw the filler
  880.             if (axis == Scrollable.HORIZONTAL) {
  881.                 g.setColor(Color.lightGray);
  882.                 g.fillRect(areaRect.x + 1, areaRect.y + 1,
  883.                            areaRect.width - 2, areaRect.height - 2);
  884.  
  885.                 g.setColor(Color.gray102);
  886.                 g.drawLine(x, maxY - 1, maxX - 1, maxY - 1);    // Bottom
  887.                 g.drawLine(otherX - 1, y, otherX - 1, maxY - 2);    // Right
  888.  
  889.                 g.setColor(Color.gray231);
  890.                 g.drawLine(beforeX, y, beforeX, maxY - 2);  // Left
  891.                 g.drawLine(beforeX + 1, y, otherX - 2, y);  // Top
  892.             } else {
  893.                 g.setColor(Color.lightGray);
  894.                 g.fillRect(areaRect.x + 1, areaRect.y + 1,
  895.                            areaRect.width - 2, areaRect.height - 2);
  896.  
  897.                 g.setColor(Color.gray102);
  898.                 g.drawLine(maxX - 1, y, maxX - 1, maxY - 1);    // Right Side
  899.                 g.drawLine(x, otherY - 1, maxX - 2, otherY - 1);    // Bottom
  900.  
  901.                 g.setColor(Color.gray231);
  902.                 g.drawLine(x, beforeY, maxX - 2, beforeY);  // Top Side
  903.                 g.drawLine(x, beforeY + 1, x, otherY - 2);  // Left side
  904.             }
  905.         }
  906.     }
  907.  
  908.     /** Redraws the ScrollBar's scroll tray and knob by computing their
  909.       * bounding rect and passing that to <b>draw()</b>.
  910.       */
  911.     public void drawScrollTray() {
  912.         Rect    tmpRect;
  913.  
  914.         tmpRect = scrollTrayRect();
  915.         addDirtyRect(tmpRect);
  916.         Rect.returnRect(tmpRect);
  917.     }
  918.  
  919.  
  920.  
  921. /* setting the knob's position and size */
  922.  
  923.  
  924.     void _setScrollValue(int newValue) {
  925.         if (newValue < 0) {
  926.             scrollValue = 0;
  927.         } else if (newValue > _maxScrollValue()) {
  928.             scrollValue = _maxScrollValue();
  929.         } else {
  930.             scrollValue = newValue;
  931.         }
  932.     }
  933.  
  934.     void _setScrollPercent(float percent) {
  935.         int     value;
  936.  
  937.         if(percent < 0.0f || percent > 1.0f)
  938.             return;
  939.         value = (int)(percent * (float)_maxScrollValue());
  940.         if (value != 0 || percent == 0.0f) {
  941.             _setScrollValue(value);
  942.         } else {
  943.             _setScrollValue((int)Math.ceil(percent *
  944.                                                 (float)_maxScrollValue()));
  945.         }
  946.     }
  947.  
  948.     void _setPercentVisible(float percent) {
  949.         int     scrollTrayLength;
  950.         int     newKnobLength;
  951.  
  952.         scrollTrayLength = scrollTrayLength();
  953.         newKnobLength = (int)(percent * scrollTrayLength);
  954.         setKnobLength(newKnobLength);
  955.  
  956.         if(scrollTrayLength < 1
  957.             || scrollTrayLength <= newKnobLength)
  958.             setActive(false);
  959.         else
  960.             setActive(true);
  961.     }
  962.  
  963.     void _computeScrollValue() {
  964.         int     scrollX,  scrollWidth, delta, contentX, contentWidth,
  965.                 oldScrollValue, oldKnobLength, theAxis;
  966.         boolean oldActive;
  967.  
  968.         oldScrollValue = scrollValue;
  969.         oldKnobLength = knobLength;
  970.         oldActive = active;
  971.         scrollX = 0;
  972.  
  973.         if(scrollableView != null) {
  974.             theAxis = axis();
  975.             scrollWidth = scrollableView.lengthOfScrollViewForAxis(theAxis);
  976.             contentWidth = scrollableView.lengthOfContentViewForAxis(theAxis);
  977.             contentX = scrollableView.positionOfContentViewForAxis(theAxis);
  978.         } else {
  979.             scrollWidth = 0;
  980.             contentWidth = 0;
  981.             contentX = 0;
  982.         }
  983.  
  984.         if (contentWidth == 0) {
  985.             _setPercentVisible(1.0f);
  986.         } else {
  987.             _setPercentVisible((float)scrollWidth / (float)contentWidth);
  988.         }
  989.  
  990.         delta = contentWidth - scrollWidth;
  991.         if (delta <= 0) {
  992.             _setScrollPercent(0.0f);
  993.         } else {
  994.             _setScrollPercent((float)(scrollX - contentX) / (float)delta);
  995.         }
  996.  
  997.         /* This logic always returns false during normal operation.
  998.          * The scrollView is telling us to update, after we've told it
  999.          * to move. I think we already have the changes and assume nothing
  1000.          * has changed. I think this may still need to be here to handle
  1001.          * the case where the user is selecting text down, past the
  1002.          * scrollView's visible region and we need to track the selection end.
  1003.          * Just a quick Look Through - ddk ALERT!
  1004.          */
  1005.  
  1006.         if ((scrollValue != oldScrollValue
  1007.              || knobLength != oldKnobLength
  1008.              || active != oldActive)
  1009.             && isActive()
  1010.             && isEnabled()) {
  1011.  
  1012.            drawScrollTray();
  1013.         }
  1014.     }
  1015.  
  1016.     /** Returns the ScrollBar's "scroll value," the pixel position of its
  1017.       * scroll knob.
  1018.       */
  1019.     public int scrollValue() {
  1020.         return scrollValue;
  1021.     }
  1022.  
  1023.     int pixelScrollValue() {
  1024.         return pixelScrollValue;
  1025.     }
  1026.  
  1027.     int _maxScrollValue() {
  1028.         return scrollTrayLength() - knobLength;
  1029.     }
  1030.  
  1031.    /** Convenience method for retrieving the scroll value as a fraction between
  1032.      * 0 and 1.
  1033.      */
  1034.     public float scrollPercent() {
  1035.         int     maxValue;
  1036.  
  1037.         maxValue = _maxScrollValue();
  1038.         if (maxValue == 0) {
  1039.             return 0.0f;
  1040.         }
  1041.  
  1042.         return (float)scrollValue() / (float)maxValue;
  1043.     }
  1044.  
  1045.     int _mouseValue(MouseEvent event) {
  1046.         Rect    scrollTrayRect;
  1047.         int     value;
  1048.  
  1049.         scrollTrayRect = scrollTrayRect();
  1050.         value = (axis == Scrollable.HORIZONTAL) ? event.x - scrollTrayRect.x :
  1051.                               event.y - scrollTrayRect.y;
  1052.         Rect.returnRect(scrollTrayRect);
  1053.  
  1054.         return value;
  1055.     }
  1056.  
  1057.     /** Overridden to allow the user to click in the scroll tray or click and
  1058.       * drag the scroll knob.
  1059.       */
  1060.     public boolean mouseDown(MouseEvent event) {
  1061.         int     oldScrollValue, delta;
  1062.  
  1063.         if (!isEnabled() || !isActive()) {
  1064.             return false;
  1065.         }
  1066.  
  1067.         lastMouseValue = lastAltMouseValue = _mouseValue(event);
  1068.  
  1069.         if (event.isMetaKeyDown()
  1070.             && ((lastMouseValue >= scrollValue + knobLength)
  1071.                 || (lastMouseValue < scrollValue))) {
  1072.             oldScrollValue = scrollValue;
  1073.             _setScrollValue(lastMouseValue - knobLength / 2);
  1074.             delta = scrollValue - oldScrollValue;
  1075.  
  1076.             if (delta != 0) {
  1077.                 scrollToCurrentPosition();
  1078.             }
  1079.         } else if (lastMouseValue < scrollValue) {
  1080.             scrollPageBackward();
  1081.             timer = new Timer(this, TIMER_SCROLL_PAGE, 75);
  1082.             timer.setInitialDelay(300);
  1083.             if (lastMouseValue < scrollValue) {
  1084.                 timer.start();
  1085.             } else if (lastMouseValue < scrollValue + (knobLength)) {
  1086.                 timer = null;
  1087.             }
  1088.         } else if (lastMouseValue >= scrollValue + (knobLength)) {
  1089.             scrollPageForward();
  1090.             timer = new Timer(this, TIMER_SCROLL_PAGE, 75);
  1091.             timer.setInitialDelay(300);
  1092.             if (lastMouseValue >= scrollValue - (knobLength)) {
  1093.                 timer.start();
  1094.             } else if (lastMouseValue >= scrollValue) {
  1095.                 timer = null;
  1096.             }
  1097.         }
  1098.  
  1099.         origScrollValue = scrollValue;
  1100.  
  1101.         return true;
  1102.     }
  1103.  
  1104.     /** Overridden to allow the user to click in the scroll tray or click and
  1105.       * drag the scroll knob.
  1106.       */
  1107.     public void mouseDragged(MouseEvent event) {
  1108.         String          command;
  1109.         int             value, delta, oldScrollValue;
  1110.  
  1111.         value = _mouseValue(event);
  1112.  
  1113.         if (!isEnabled() || !isActive() || timer != null) {
  1114.             lastMouseValue = value;
  1115.             origScrollValue = scrollValue;
  1116.             return;
  1117.         }
  1118.  
  1119.         if (event.isControlKeyDown()) {
  1120.             pixelScrollValue = lastAltMouseValue - value;
  1121.             scrollByPixel(pixelScrollValue);
  1122.             lastAltMouseValue = value;
  1123.             origScrollValue = scrollValue;
  1124.  
  1125.             return;
  1126.         }
  1127.  
  1128.         lastAltMouseValue = value;
  1129.  
  1130.         oldScrollValue = scrollValue;
  1131.         _setScrollValue(origScrollValue + (value - lastMouseValue));
  1132.         delta = scrollValue - oldScrollValue;
  1133.  
  1134.         if (delta != 0) {
  1135.             scrollToCurrentPosition();
  1136.         }
  1137.     }
  1138.  
  1139.     private void timerScroll() {
  1140.         if (lastMouseValue < scrollValue) {
  1141.             scrollPageBackward();
  1142.             if (lastMouseValue >= scrollValue) {
  1143.                 timer.stop();
  1144.                 if (lastMouseValue < scrollValue + (knobLength)) {
  1145.                     timer = null;
  1146.                 }
  1147.             }
  1148.         } else if (lastMouseValue >= scrollValue + (knobLength)) {
  1149.             scrollPageForward();
  1150.             if (lastMouseValue < scrollValue - (knobLength)) {
  1151.                 timer.stop();
  1152.                 if (lastMouseValue >= scrollValue) {
  1153.                     timer = null;
  1154.                 }
  1155.             }
  1156.         }
  1157.         origScrollValue = scrollValue;
  1158.     }
  1159.  
  1160.     /** Overridden to allow the user to click in the scroll tray or click and
  1161.       * drag the scroll knob.
  1162.       */
  1163.     public void mouseUp(MouseEvent event) {
  1164.         if (timer != null) {
  1165.             timer.stop();
  1166.             timer = null;
  1167.         }
  1168.     }
  1169.  
  1170.     /** Implements the ScrollBar's commands.
  1171.       */
  1172.     public void performCommand(String command, Object data) {
  1173.         if (TIMER_SCROLL_PAGE.equals(command)) {
  1174.             timerScroll();
  1175.         } else if(UPDATE.equals(command)) {
  1176.             update();
  1177.         } else if(SCROLL_LINE_FORWARD.equals(command))  {
  1178.             scrollLineForward();
  1179.         } else if(SCROLL_LINE_BACKWARD.equals(command))  {
  1180.             scrollLineBackward();
  1181.         } else if(SCROLL_PAGE_FORWARD.equals(command))  {
  1182.             scrollPageForward();
  1183.         } else if(SCROLL_PAGE_BACKWARD.equals(command))  {
  1184.             scrollPageBackward();
  1185.         } else  {
  1186.             throw new NoSuchMethodError("unknown command: " + command);
  1187.         }
  1188.     }
  1189.  
  1190.     private void update() {
  1191.         int             oldScrollValue, oldKnobLength;
  1192.         boolean         oldActive;
  1193.  
  1194.         /* have to force the drawing, even though _computeScrollValue()
  1195.          * makes the same call - not sure why
  1196.          * See comment under _computeScrollValue for current theory - ddk
  1197.          */
  1198.         oldScrollValue = scrollValue;
  1199.         oldKnobLength = knobLength;
  1200.         oldActive = active;
  1201.  
  1202.         oldActive = active;
  1203.         _computeScrollValue();
  1204.  
  1205.         if (oldActive != active) {
  1206.             setDirty(true);
  1207.         } else if (shouldRedraw || (scrollValue != oldScrollValue ||
  1208.                     knobLength != oldKnobLength || active != oldActive) &&
  1209.                     isActive() && isEnabled()) {
  1210.             drawScrollTray();
  1211.         }
  1212.     }
  1213.  
  1214. /* archiving */
  1215.  
  1216.  
  1217.     /** Describes the ScrollBar class' information.
  1218.       * @see Codable#describeClassInfo
  1219.       */
  1220.     public void describeClassInfo(ClassInfo info) {
  1221.         super.describeClassInfo(info);
  1222.  
  1223.         info.addClass("netscape.application.ScrollBar", 2);
  1224.         info.addField(SCROLLVIEW_KEY, OBJECT_TYPE);
  1225.         info.addField(INCREASEBUTTON_KEY, OBJECT_TYPE);
  1226.         info.addField(DECREASEBUTTON_KEY, OBJECT_TYPE);
  1227.         info.addField(KNOBIMAGE_KEY, OBJECT_TYPE);
  1228.         info.addField(SCROLLVALUE_KEY, INT_TYPE);
  1229.         info.addField(AXIS_KEY, INT_TYPE);
  1230.         info.addField(ACTIVE_KEY, BOOLEAN_TYPE);
  1231.         info.addField(ENABLED_KEY, BOOLEAN_TYPE);
  1232.         info.addField(LINE_INCREMENT_KEY, INT_TYPE);
  1233.         info.addField(OWNER_KEY, OBJECT_TYPE);
  1234.     }
  1235.  
  1236.     /** Encodes the ScrollBar instance.
  1237.       * @see Codable#encode
  1238.       */
  1239.     public void encode(Encoder encoder) throws CodingException {
  1240.         super.encode(encoder);
  1241.  
  1242.         encoder.encodeObject(SCROLLVIEW_KEY, scrollableView);
  1243.         encoder.encodeObject(INCREASEBUTTON_KEY, increaseButton);
  1244.         encoder.encodeObject(DECREASEBUTTON_KEY, decreaseButton);
  1245.         encoder.encodeObject(KNOBIMAGE_KEY, knobImage);
  1246.         encoder.encodeInt(SCROLLVALUE_KEY, scrollValue);
  1247.         encoder.encodeInt(AXIS_KEY, axis);
  1248.         encoder.encodeBoolean(ACTIVE_KEY, active);
  1249.         encoder.encodeBoolean(ENABLED_KEY, enabled);
  1250.         encoder.encodeInt(LINE_INCREMENT_KEY, lineIncrement);
  1251.         encoder.encodeObject(OWNER_KEY, scrollBarOwner);
  1252.     }
  1253.  
  1254.     /** Decodes the ScrollBar instance.
  1255.       * @see Codable#decode
  1256.       */
  1257.     public void decode(Decoder decoder) throws CodingException {
  1258.         int version = decoder.versionForClassName("netscape.application.ScrollBar");
  1259.         super.decode(decoder);
  1260.  
  1261.         scrollableView = (Scrollable)decoder.decodeObject(SCROLLVIEW_KEY);
  1262.         increaseButton = (Button)decoder.decodeObject(INCREASEBUTTON_KEY);
  1263.         decreaseButton = (Button)decoder.decodeObject(DECREASEBUTTON_KEY);
  1264.         knobImage = (Image)decoder.decodeObject(KNOBIMAGE_KEY);
  1265.         scrollValue = decoder.decodeInt(SCROLLVALUE_KEY);
  1266.         axis = decoder.decodeInt(AXIS_KEY);
  1267.         active = decoder.decodeBoolean(ACTIVE_KEY);
  1268.         enabled = decoder.decodeBoolean(ENABLED_KEY);
  1269.  
  1270.         if(version >= 2)    {
  1271.             lineIncrement = decoder.decodeInt(LINE_INCREMENT_KEY);
  1272.             scrollBarOwner = (ScrollBarOwner)decoder.decodeObject(OWNER_KEY);
  1273.         } else  {
  1274.             lineIncrement = DEFAULT_LINE_INCREMENT;
  1275.             scrollBarOwner = null;
  1276.         }
  1277.  
  1278.         _computeScrollValue();
  1279.     }
  1280.  
  1281.  
  1282.     /** Returns the axis controlled by this ScrollBar. */
  1283.     public int axis()   {
  1284.         return axis;
  1285.     }
  1286.  
  1287.     /** Returns the ScrollBar's page size as a percentage of the
  1288.       * <b>lengthOfScrollViewForAxis()</b> value.
  1289.       * @see #setPageSizeAsPercent
  1290.       * @see Scrollable#lengthOfScrollViewForAxis
  1291.       */
  1292.     public float pageSizeAsPercent()    {
  1293.         return pageSizeAsPercent;
  1294.     }
  1295.  
  1296.     /** Sets the ScrollBar's page size. When asked to scroll
  1297.       * one page, the ScrollView determines the number of pixels
  1298.       * to scroll by multiplying this percentage by the appropriate axis
  1299.       * length.
  1300.       * @see #setPageSizeAsPercent
  1301.       */
  1302.     public void setPageSizeAsPercent(float value)   {
  1303.         if (value <= 0.0f || value > 1.0f) {
  1304.             return;
  1305.         }
  1306.         pageSizeAsPercent = value;
  1307.     }
  1308.  
  1309.     /** Sets the ScrollBar's line increment. This line increment
  1310.       * is the number of pixels that the ScrollBar scrolls the Scrollable
  1311.       * object when asked to scroll by lines.
  1312.       */
  1313.     public void setLineIncrement(int value) {
  1314.         if(value > 0)   {
  1315.             lineIncrement = value;
  1316.         }
  1317.     }
  1318.  
  1319.     /** Returns the ScrollBar's line increment.
  1320.       * @see #setLineIncrement
  1321.       */
  1322.     public int lineIncrement()  {
  1323.         return lineIncrement;
  1324.     }
  1325.  
  1326. /* Scrolling control methods */
  1327.  
  1328.     /** Primitive method that sends the scrollTo method to the Scrolling view.
  1329.       * Handy place to wrap the shouldRedraw sets
  1330.       */
  1331.     private void scrollTo(int x, int y)  {
  1332.         shouldRedraw = true;
  1333.         if(scrollableView != null)
  1334.             scrollableView.scrollTo(x,y);
  1335.         shouldRedraw = false;
  1336.     }
  1337.  
  1338.     /** Primitive method that sends the scrollBy method to the Scrolling view.
  1339.       * Handy place to wrap the shouldRedraw sets
  1340.       */
  1341.     private void scrollBy(int deltaX, int deltaY)  {
  1342.         shouldRedraw = true;
  1343.         if(scrollableView != null) {
  1344.             scrollableView.scrollBy(deltaX, deltaY);
  1345.         }
  1346.         shouldRedraw = false;
  1347.     }
  1348.  
  1349.     /** Scrolls the Scrollable object the amount of pixels along the axis.
  1350.       */
  1351.     private void scrollByPixel(int amount) {
  1352.         if(scrollableView != null) {
  1353.             if(axis == Scrollable.HORIZONTAL)
  1354.                 scrollBy(amount,0);
  1355.             else
  1356.                 scrollBy(0,amount);
  1357.         }
  1358.     }
  1359.  
  1360.     /** Scrolls the Scrollable object the amount of lines along the axis.
  1361.       */
  1362.     private void scrollByLine(int amount)  {
  1363.         if(scrollableView != null) {
  1364.             if(axis == Scrollable.HORIZONTAL)
  1365.                 scrollBy(amount*lineIncrement,0);
  1366.             else
  1367.                 scrollBy(0,amount*lineIncrement);
  1368.         }
  1369.     }
  1370.  
  1371.     /** Scrolls the Scrollable object the amount of pages along the axis.
  1372.       * Amount is some percent of a page. Normally this is defaulted to 1.0f
  1373.       * to scroll a single page.
  1374.       */
  1375.     private void scrollByPage(float amount)  {
  1376.         if(scrollableView != null) {
  1377.             if(axis == Scrollable.HORIZONTAL)
  1378.                 scrollBy((int)(amount*scrollableView.lengthOfScrollViewForAxis(axis)),0);
  1379.             else
  1380.                 scrollBy(0,(int)(amount*scrollableView.lengthOfScrollViewForAxis(axis)));
  1381.         }
  1382.     }
  1383.  
  1384.     /** Scrolls the Scrollable object to a specific amount relative to the top
  1385.       * or left of the Scrollable object.
  1386.       */
  1387.     private void scrollToPercent(float amount) {
  1388.         int scrollLen, contentLen, contentPosition, newAxis;
  1389.         if(scrollableView != null) {
  1390.             scrollLen = scrollableView.lengthOfContentViewForAxis(axis);
  1391.             contentLen = scrollableView.lengthOfScrollViewForAxis(axis);
  1392.             newAxis = -(int)(amount * (float)(scrollLen  - contentLen));
  1393.             if(axis == Scrollable.HORIZONTAL)
  1394.                 scrollTo(newAxis,scrollableView.positionOfContentViewForAxis(Scrollable.VERTICAL));
  1395.             else
  1396.                 scrollTo(scrollableView.positionOfContentViewForAxis(Scrollable.HORIZONTAL),newAxis);
  1397.         }
  1398.     }
  1399.  
  1400.     /** Scrolls the Scrollable object the appropriate direction by
  1401.       * <b>lineIncrement()</b> pixels. Forward is to the right or down.
  1402.       * @see #lineIncrement
  1403.       */
  1404.     public void scrollLineForward() {
  1405.         scrollByLine(-1);
  1406.     }
  1407.  
  1408.     /** Scrolls the Scrollable object the appropriate direction by
  1409.       * <b>lineIncrement()</b> pixels. Backward is to the left or up.
  1410.       * @see #lineIncrement
  1411.       */
  1412.     public void scrollLineBackward()    {
  1413.         scrollByLine(1);
  1414.     }
  1415.  
  1416.     /** Scrolls the Scrollable object the appropriate direction by
  1417.       *<b>pageSizeAsPercent()</b> pixels. Forward is to the right or down.
  1418.       * @see #pageSizeAsPercent
  1419.       */
  1420.     public void scrollPageForward() {
  1421.         scrollByPage(-pageSizeAsPercent);
  1422.     }
  1423.  
  1424.     /** Scrolls the Scrollable object the appropriate direction by
  1425.       * <b>pageSizeAsPercent()</b> pixels. Backward is to the left or up.
  1426.       * @see #pageSizeAsPercent
  1427.       */
  1428.     public void scrollPageBackward()    {
  1429.         scrollByPage(pageSizeAsPercent);
  1430.     }
  1431.  
  1432.     /** Scrolls the Scrollable object to match the current value returned by
  1433.       * <b>scrollPercent()</b>.
  1434.       * @see #scrollPercent
  1435.       */
  1436.     public void scrollToCurrentPosition()   {
  1437.         scrollToPercent(scrollPercent());
  1438.     }
  1439.  
  1440.     /** Scrolls <b>value</b> percent into the contentView.
  1441.       * @see #scrollPercent
  1442.       */
  1443.     public void setScrollPercent(float value)   {
  1444.         _setScrollPercent(value);
  1445.         scrollToCurrentPosition();
  1446.     }
  1447.  
  1448.     void _setupKeyboard() {
  1449.         removeAllCommandsForKeys();
  1450.         if(axis() == Scrollable.HORIZONTAL) {
  1451.             setCommandForKey(SCROLL_LINE_FORWARD,KeyEvent.RIGHT_ARROW_KEY,View.WHEN_IN_MAIN_WINDOW);
  1452.             setCommandForKey(SCROLL_LINE_BACKWARD,KeyEvent.LEFT_ARROW_KEY,View.WHEN_IN_MAIN_WINDOW);
  1453.         } else {
  1454.             setCommandForKey(SCROLL_LINE_FORWARD,KeyEvent.DOWN_ARROW_KEY,View.WHEN_IN_MAIN_WINDOW);
  1455.             setCommandForKey(SCROLL_LINE_BACKWARD,KeyEvent.UP_ARROW_KEY,View.WHEN_IN_MAIN_WINDOW);
  1456.         }
  1457.     }
  1458.  
  1459.     /** Overridden to return <b>true</b>.
  1460.       *
  1461.       */
  1462.     public boolean hidesSubviewsFromKeyboard() {
  1463.         return true;
  1464.     }
  1465. }
  1466.